home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / pctchnqs / 1992 / number2 / l1.cpp < prev    next >
Text File  |  1992-03-21  |  6KB  |  195 lines

  1. /* C++ Game of Life implementation for any mode for which mode set
  2.    and draw pixel functions can be provided.
  3.    Tested with Borland C++ 3.0 in the small model. */
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <iostream.h>
  7. #include <conio.h>
  8. #include <time.h>
  9. #include <dos.h>
  10. #include <bios.h>
  11. #include <mem.h>
  12.  
  13. #define ON_COLOR  15       // on-cell pixel color
  14. #define OFF_COLOR 0        // off-cell pixel color
  15. #define MSG_LINE  10       // row for text messages
  16. #define GENERATION_LINE 12 // row for generation # display
  17. #define LIMIT_18_HZ  1     // set 1 for maximum frame rate = 18Hz
  18. #define WRAP_EDGES   1     // set to 0 to disable wrapping around
  19.                            // at cell map edges
  20. class cellmap {
  21. private:
  22.    unsigned char *cells;
  23.    unsigned int width;
  24.    unsigned int width_in_bytes;
  25.    unsigned int height;
  26.    unsigned int length_in_bytes;
  27. public:
  28.    cellmap(unsigned int h, unsigned int v);
  29.    ~cellmap(void);
  30.    void copy_cells(cellmap &sourcemap);
  31.    void set_cell(unsigned int x, unsigned int y);
  32.    void clear_cell(unsigned int x, unsigned int y);
  33.    int cell_state(int x, int y);
  34.    void next_generation(cellmap& dest_map);
  35. };
  36.  
  37. extern void enter_display_mode(void);
  38. extern void exit_display_mode(void);
  39. extern void draw_pixel(unsigned int X, unsigned int Y,
  40.    unsigned int Color);
  41. extern void show_text(int x, int y, char *text);
  42.  
  43. /* Controls the size of the cell map. Must be within the capabilities
  44.    of the display mode, and must be limited to leave room for text
  45.    display at right. */
  46. unsigned int cellmap_width = 96;
  47. unsigned int cellmap_height = 96;
  48. /* Width & height in pixels of each cell as displayed on screen. */
  49. unsigned int magnifier = 2;
  50.  
  51. void main()
  52. {
  53.    unsigned int init_length, x, y, seed;
  54.    unsigned long generation = 0;
  55.    char gen_text[80];
  56.    long bios_time, start_bios_time;
  57.  
  58.    cellmap current_map(cellmap_height, cellmap_width);
  59.    cellmap next_map(cellmap_height, cellmap_width);
  60.  
  61.    // Get the seed; seed randomly if 0 entered
  62.    cout << "Seed (0 for random seed): ";
  63.    cin >> seed;
  64.    if (seed == 0) seed = (unsigned) time(NULL);
  65.  
  66.    // Randomly initialize the initial cell map
  67.    cout << "Initializing...";
  68.    srand(seed);
  69.    init_length = (cellmap_height * cellmap_width) / 2;
  70.    do {
  71.       x = random(cellmap_width);
  72.       y = random(cellmap_height);
  73.       next_map.set_cell(x, y);
  74.    } while (--init_length);
  75.    current_map.copy_cells(next_map); // put init map in current_map
  76.  
  77.    enter_display_mode();
  78.  
  79.    // Keep recalculating and redisplaying generations until a key
  80.    // is pressed
  81.    show_text(0, MSG_LINE, "Generation: ");
  82.    start_bios_time = _bios_timeofday(_TIME_GETCLOCK, &bios_time);
  83.    do {
  84.       generation++;
  85.       sprintf(gen_text, "%10lu", generation);
  86.       show_text(1, GENERATION_LINE, gen_text);
  87.       // Recalculate and draw the next generation
  88.       current_map.next_generation(next_map);
  89.       // Make current_map current again
  90.       current_map.copy_cells(next_map);
  91. #if LIMIT_18_HZ
  92.       // Limit to a maximum of 18.2 frames per second, for visibility
  93.       do {
  94.          _bios_timeofday(_TIME_GETCLOCK, &bios_time);
  95.       } while (start_bios_time == bios_time);
  96.       start_bios_time = bios_time;
  97. #endif
  98.    } while (!kbhit());
  99.    getch();    // clear keypress
  100.    exit_display_mode();
  101.    cout << "Total generations: " << generation << "\nSeed: " <<
  102.          seed << "\n";
  103. }
  104.  
  105. /* cellmap constructor. */
  106. cellmap::cellmap(unsigned int h, unsigned int w)
  107. {
  108.    width = w;
  109.    width_in_bytes = (w + 7) / 8;
  110.    height = h;
  111.    length_in_bytes = width_in_bytes * h;
  112.    cells = new unsigned char[length_in_bytes];  // cell storage
  113.    memset(cells, 0, length_in_bytes);  // clear all cells, to start
  114. }
  115.  
  116. /* cellmap destructor. */
  117. cellmap::~cellmap(void)
  118. {
  119.    delete[] cells;
  120. }
  121.  
  122. /* Copies one cellmap's cells to another cellmap. Both cellmaps are
  123.    assumed to be the same size.  */
  124. void cellmap::copy_cells(cellmap &sourcemap)
  125. {
  126.    memcpy(cells, sourcemap.cells, length_in_bytes);
  127. }
  128.  
  129. /* Turns cell on. */
  130. void cellmap::set_cell(unsigned int x, unsigned int y)
  131. {
  132.    unsigned char *cell_ptr =
  133.          cells + (y * width_in_bytes) + (x / 8);
  134.  
  135.    *(cell_ptr) |= 0x80 >> (x & 0x07);
  136. }
  137.  
  138. /* Turns cell off. */
  139. void cellmap::clear_cell(unsigned int x, unsigned int y)
  140. {
  141.    unsigned char *cell_ptr =
  142.          cells + (y * width_in_bytes) + (x / 8);
  143.  
  144.    *(cell_ptr) &= ~(0x80 >> (x & 0x07));
  145. }
  146.  
  147. /* Returns cell state (1=on or 0=off), optionally wrapping at the
  148.    borders around to the opposite edge. */
  149. int cellmap::cell_state(int x, int y)
  150. {
  151.    unsigned char *cell_ptr;
  152.  
  153. #if WRAP_EDGES
  154.    while (x < 0) x += width;     // wrap, if necessary
  155.    while (x >= width) x -= width;
  156.    while (y < 0) y += height;
  157.    while (y >= height) y -= height;
  158. #else
  159.    if ((x < 0) || (x >= width) || (y < 0) || (y >= height))
  160.       return 0;   // return 0 for off edges if no wrapping
  161. #endif
  162.    cell_ptr = cells + (y * width_in_bytes) + (x / 8);
  163.    return (*cell_ptr & (0x80 >> (x & 0x07))) ? 1 : 0;
  164. }
  165.  
  166. /* Calculates the next generation of a cellmap and stores it in
  167.    next_map. */
  168. void cellmap::next_generation(cellmap& next_map)
  169. {
  170.    unsigned int x, y, neighbor_count;
  171.  
  172.    for (y=0; y<height; y++) {
  173.       for (x=0; x<width; x++) {
  174.          // Figure out how many neighbors this cell has
  175.          neighbor_count = cell_state(x-1, y-1) + cell_state(x, y-1) +
  176.                cell_state(x+1, y-1) + cell_state(x-1, y) +
  177.                cell_state(x+1, y) + cell_state(x-1, y+1) +
  178.                cell_state(x, y+1) + cell_state(x+1, y+1);
  179.          if (cell_state(x, y) == 1) {
  180.             // The cell is on; does it stay on?
  181.             if ((neighbor_count != 2) && (neighbor_count != 3)) {
  182.                next_map.clear_cell(x, y);    // turn it off
  183.                draw_pixel(x, y, OFF_COLOR);
  184.             }
  185.          } else {
  186.             // The cell is off; does it turn on?
  187.             if (neighbor_count == 3) {
  188.                next_map.set_cell(x, y);      // turn it on
  189.                draw_pixel(x, y, ON_COLOR);
  190.             }
  191.          }
  192.       }
  193.    }
  194. }
  195.